import { ForbiddenException } from '@nestjs/common'

import { MenuType } from '~/enums'
import { envBoolean } from '~/global/env'
import { MenuEntity } from '~/modules/system/menu/menu.entity'

// 菜单路由接口
export interface MenuRoute {
  id: number
  parentId: number
  name: string
  path: string
  component?: string
  componentName?: string
  icon: string
  visible: boolean
  keepAlive: boolean
  alwaysShow: boolean
  children?: MenuRoute[] | null
}

function createRoute(menu: MenuEntity, _isRoot: boolean): MenuRoute {
  // 转换 bit 类型字段为布尔值
  const convertBitToBoolean = (value: any): boolean => {
    if (typeof value === 'boolean')
      return value
    if (typeof value === 'number')
      return value === 1
    if (value && typeof value === 'object' && value.type === 'Buffer') {
      return value.data[0] === 1
    }
    return Boolean(value)
  }

  const baseRoute: MenuRoute = {
    id: menu.id,
    parentId: menu.parentId,
    name: menu.name,
    path: menu.path,
    component: menu.component,
    componentName: menu.componentName,
    icon: menu.icon,
    visible: convertBitToBoolean(menu.visible),
    keepAlive: convertBitToBoolean(menu.keepAlive),
    alwaysShow: convertBitToBoolean(menu.alwaysShow),
  }

  return baseRoute
}

function filterAsyncRoutes(menus: MenuEntity[], parentRoute: MenuEntity | null): MenuRoute[] {
  const res: MenuRoute[] = []

  menus.forEach((menu) => {
    if (menu.type === MenuType.PERMISSION || menu.status === 1) {
      // 如果是权限或禁用直接跳过
      return
    }

    const isRoot = !parentRoute && (Number(menu.parentId) === 0 || menu.parentId === null)
    const isChild = parentRoute && Number(parentRoute.id) === Number(menu.parentId)

    if (isRoot) {
      // 根级别菜单
      if (menu.type === MenuType.MENU_GROUP) {
        // 根目录
        const childRoutes = filterAsyncRoutes(menus, menu)
        const realRoute = createRoute(menu, true)
        if (childRoutes && childRoutes.length > 0) {
          realRoute.children = childRoutes
        }
        else {
          realRoute.children = null
        }
        res.push(realRoute)
      }
      else if (menu.type === MenuType.MENU) {
        // 根菜单
        const realRoute = createRoute(menu, true)
        realRoute.children = null
        res.push(realRoute)
      }
    }
    else if (isChild) {
      // 子级别菜单
      if (menu.type === MenuType.MENU_GROUP) {
        // 子目录
        const childRoutes = filterAsyncRoutes(menus, menu)
        const realRoute = createRoute(menu, false)
        if (childRoutes && childRoutes.length > 0) {
          realRoute.children = childRoutes
        }
        else {
          realRoute.children = null
        }
        res.push(realRoute)
      }
      else if (menu.type === MenuType.MENU) {
        // 子菜单
        const realRoute = createRoute(menu, false)
        realRoute.children = null
        res.push(realRoute)
      }
    }
  })

  return res
}

export function generatorRouters(menus: MenuEntity[]) {
  return filterAsyncRoutes(menus, null)
}

// 获取所有菜单以及权限
function filterMenuToTable(menus: MenuEntity[], parentMenu) {
  const res = []
  menus.forEach((menu) => {
    // 根级别菜单渲染
    let realMenu
    if (!parentMenu && !menu.parentId && menu.type === MenuType.MENU) {
      // 根菜单，查找该跟菜单下子菜单，因为可能会包含权限
      const childMenu = filterMenuToTable(menus, menu)
      realMenu = { ...menu }
      realMenu.children = childMenu
    }
    else if (!parentMenu && !menu.parentId && menu.type === MenuType.MENU_GROUP) {
      // 根目录
      const childMenu = filterMenuToTable(menus, menu)
      realMenu = { ...menu }
      realMenu.children = childMenu
    }
    else if (parentMenu && parentMenu.id === menu.parentId && menu.type === MenuType.MENU) {
      // 子菜单下继续找是否有子菜单
      const childMenu = filterMenuToTable(menus, menu)
      realMenu = { ...menu }
      realMenu.children = childMenu
    }
    else if (parentMenu && parentMenu.id === menu.parentId && menu.type === MenuType.MENU_GROUP) {
      // 如果还是目录，继续递归
      const childMenu = filterMenuToTable(menus, menu)
      realMenu = { ...menu }
      realMenu.children = childMenu
    }
    else if (parentMenu && parentMenu.id === menu.parentId && menu.type === MenuType.PERMISSION) {
      realMenu = { ...menu }
    }
    // add curent route
    if (realMenu) {
      realMenu.pid = menu.id
      res.push(realMenu)
    }
  })
  return res
}

export function generatorMenu(menu: MenuEntity[]) {
  return filterMenuToTable(menu, null)
}

/** 检测是否为演示环境, 如果为演示环境，则拒绝该操作 */
export function checkIsDemoMode() {
  if (envBoolean('IS_DEMO'))
    throw new ForbiddenException('演示模式下不允许操作')
}
